/*
	
案例1.实现功能：
id_table 功能，
 一个驱动匹配 多个设备 
  获取devices描述中断号，寄存器地址

 
static const struct platform_device_id led_id_table[] = {
	{
		.name = "rk3399_led",
		.driver_data = 0x1,
	}, {
		.name = "rk3288_led",
		.driver_data = 0x2,
	}, {
		.name = "rk3568_led",
		.driver_data = 0x3,
	}, {
		/* id table 定义多个 .name , 匹配到不同的.name 读取到不同硬件描述
       走同一个驱动
      

  
如何获取引脚号：
上面①.在devices的属性resource 传递地址，和中断号，描述硬件
缺项不能描述 引脚号， 
自定义数据通过这个属性：platform_device->devices->platform_data 是 void * 
可以定义一个结构体，给这个成员，复制给上面 ，通过这个结构体描述gpio,  传递给driver 

定义rk_gpio_led，描述引脚号和名称， 丢给leds_platform_data结构体， 在给上面的void* 


[21414.139745] <kernel> call driver_mod_init()
[21414.140640] <kernel> addr_res->start=0xff76037c end=0xff76037f
[21414.141166] <kernel> addr_res->start=0xff77e000 end=0xff77e003
[21414.141781] <kernel> addr_res->start=0xff780004 end=0xff780007
[21414.142301] <kernel> addr_res->start=0xff780000 end=0xff780003
[21414.142923] <kernel> irq_res->start=0x4b end=0x4b
[21414.143347] <kernel> irqno= 75
[21414.143650] <kernel> gpiono=55  desc=gpio_led2_green 
[21414.144108] <kernel> gpiono=56  desc=gpio_led2_orange 
[21414.144625] <kernel> gpiono=13  desc=gpio_led1 



  
*/


#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include "led.h"


//当平台驱动和平台设备匹配时调用probe函数
static int led_probe(struct platform_device *pdev)
{
	int i;
	int irqno;
	//pdev对象就是匹配成功的平台设备对象
	struct resource *addr_res, *irq_res;
	struct leds_platform_data *pdata = NULL;
	pdata = (struct leds_platform_data *)pdev->dev.platform_data;
	
	if (!pdata) {
		printk("<kernel> leds_platform_data get fail\n");
		return -EINVAL;
	}
	
	for (i = 0; i < 4; i++) {
		addr_res = platform_get_resource(pdev, IORESOURCE_MEM, i);
		printk("<kernel> addr_res->start=0x%llx end=0x%llx\n", addr_res->start, addr_res->end);
	}

	irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	printk("<kernel> irq_res->start=0x%llx end=0x%llx\n", irq_res->start, irq_res->end);
	
	irqno = platform_get_irq(pdev, 0);
	printk("<kernel> irqno= %d\n", irqno);


	for (i = 0; i < pdata->nleds; i++) 
		printk("<kernel> gpiono=%d  desc=%s \n", pdata->leds[i].gpio, pdata->leds[i].desc);

	printk("<kernel> call %s()\n", __func__);  
	return 0;
}

//当平台驱动和平台设备分离时调用remove函数
static int led_remove(struct platform_device *pdev)
{
	printk("<kernel> call %s()\n", __func__);  
	return 0;

}

static const struct platform_device_id led_id_table[] = {
	{
		.name = "rk3399_led",
		.driver_data = 0x1,
	}, {
		.name = "rk3288_led",
		.driver_data = 0x2,
	}, {
		.name = "rk3568_led",
		.driver_data = 0x3,
	}, {
		/* id table */
	}
};



//定义平台驱动对象并初始化
static struct platform_driver rk_led_driver = {
	.probe		= led_probe,
	.remove		= led_remove,
	.driver		= {
		.name	= "rk_led", //平台驱动的字符串名称,也是匹配的条件
	},
	.id_table = led_id_table, //指向匹配平台设备的数组
};



static int __init driver_mod_init(void)
{
	printk("<kernel> call %s()\n", __func__);  
	return platform_driver_register(&rk_led_driver);
}


static void __exit driver_mod_exit(void)
{
	printk("<kernel> call %s() @ %d\n", __FUNCTION__, __LINE__);  
	platform_driver_unregister(&rk_led_driver);
}


module_init(driver_mod_init); 
module_exit(driver_mod_exit); 
MODULE_LICENSE("GPL"); 



